//package com.hl.framework.tenant.config;
//
//import cn.hutool.extra.spring.SpringUtil;
//import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
//import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
//
//import com.hl.framework.auth.service.SecurityFrameworkService;
//import com.hl.framework.core.common.enums.WebFilterOrderEnum;
//import com.hl.framework.db.mybatis.util.MyBatisUtils;
//import com.hl.framework.tenant.core.aop.TenantIgnore;
//import com.hl.framework.tenant.core.aop.TenantIgnoreAspect;
//import com.hl.framework.tenant.core.db.TenantDatabaseInterceptor;
//import com.hl.framework.tenant.core.service.TenantFrameworkService;
//import com.hl.framework.tenant.core.service.TenantFrameworkServiceImpl;
//import com.hl.framework.tenant.core.web.TenantContextWebFilter;
//import com.hl.framework.tenant.core.web.TenantVisitContextInterceptor;
//import jakarta.annotation.Resource;
//import org.springframework.boot.autoconfigure.AutoConfiguration;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
//import org.springframework.boot.context.properties.EnableConfigurationProperties;
//import org.springframework.boot.web.servlet.FilterRegistrationBean;
//import org.springframework.context.ApplicationContext;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.context.annotation.Primary;
//
//import org.springframework.web.method.HandlerMethod;
//import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
//import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
//import org.springframework.web.util.pattern.PathPattern;
//
//import java.util.Map;
//import java.util.Objects;
//
//import static com.hl.framework.core.common.util.collection.CollectionUtils.convertList;
//
//
//@AutoConfiguration
//@ConditionalOnProperty(prefix = "handlink.tenant", value = "enable", matchIfMissing = true) // 允许使用 handlink.tenant.enable=false 禁用多租户
//@EnableConfigurationProperties(TenantProperties.class)
//public class HandlinkTenantAutoConfiguration {
//
//    @Resource
//    private ApplicationContext applicationContext;
//
//    @Bean
//    public TenantFrameworkService tenantFrameworkService(TenantCommonApi tenantApi) {
//        // 参见 https://gitee.com/zhijiantianya/handlink-cloud/issues/IC6YZF
//        try {
//            TenantCommonApi tenantApiImpl = SpringUtil.getBean("tenantApiImpl", TenantCommonApi.class);
//            if (tenantApiImpl != null) {
//                tenantApi = tenantApiImpl;
//            }
//        } catch (Exception ignored) {}
//        return new TenantFrameworkServiceImpl(tenantApi);
//    }
//
//    // ========== AOP ==========
//
//    @Bean
//    public TenantIgnoreAspect tenantIgnoreAspect() {
//        return new TenantIgnoreAspect();
//    }
//
//    // ========== DB ==========
//
//    @Bean
//    public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties properties,
//                                                                 MybatisPlusInterceptor interceptor) {
//        TenantLineInnerInterceptor inner = new TenantLineInnerInterceptor(new TenantDatabaseInterceptor(properties));
//        // 添加到 interceptor 中
//        // 需要加在首个，主要是为了在分页插件前面。这个是 MyBatis Plus 的规定
//        MyBatisUtils.addInterceptor(interceptor, inner, 0);
//        return inner;
//    }
//
//    // ========== WEB ==========
//
//    @Bean
//    public FilterRegistrationBean<TenantContextWebFilter> tenantContextWebFilter(TenantProperties tenantProperties) {
//        FilterRegistrationBean<TenantContextWebFilter> registrationBean = new FilterRegistrationBean<>();
//        registrationBean.setFilter(new TenantContextWebFilter());
//        registrationBean.setOrder(WebFilterOrderEnum.TENANT_CONTEXT_FILTER);
//        addIgnoreUrls(tenantProperties);
//        return registrationBean;
//    }
//
//    /**
//     * 如果 Controller 接口上，有 {@link TenantIgnore} 注解，那么添加到忽略的 URL 中
//     *
//     * @param tenantProperties 租户配置
//     */
//    private void addIgnoreUrls(TenantProperties tenantProperties) {
//        // 获得接口对应的 HandlerMethod 集合
//        RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping)
//                applicationContext.getBean("requestMappingHandlerMapping");
//        Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
//        // 获得有 @TenantIgnore 注解的接口
//        for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethodMap.entrySet()) {
//            HandlerMethod handlerMethod = entry.getValue();
//            if (!handlerMethod.hasMethodAnnotation(TenantIgnore.class)) {
//                continue;
//            }
//            // 添加到忽略的 URL 中
//            if (entry.getKey().getPatternsCondition() != null) {
//                tenantProperties.getIgnoreUrls().addAll(entry.getKey().getPatternsCondition().getPatterns());
//            }
//            if (entry.getKey().getPathPatternsCondition() != null) {
//                tenantProperties.getIgnoreUrls().addAll(
//                        convertList(entry.getKey().getPathPatternsCondition().getPatterns(), PathPattern::getPatternString));
//            }
//        }
//    }
//
//    @Bean
//    public TenantVisitContextInterceptor tenantVisitContextInterceptor(TenantProperties tenantProperties,
//                                                                       SecurityFrameworkService securityFrameworkService) {
//        return new TenantVisitContextInterceptor(tenantProperties, securityFrameworkService);
//    }
//
//    @Bean
//    public WebMvcConfigurer tenantWebMvcConfigurer(TenantProperties tenantProperties,
//                                                   TenantVisitContextInterceptor tenantVisitContextInterceptor) {
//        return new WebMvcConfigurer() {
//
//            @Override
//            public void addInterceptors(InterceptorRegistry registry) {
//                registry.addInterceptor(tenantVisitContextInterceptor)
//                        .excludePathPatterns(tenantProperties.getIgnoreVisitUrls().toArray(new String[0]));
//            }
//        };
//    }
//
//    // ========== Security ==========
//
//    @Bean
//    public FilterRegistrationBean<TenantSecurityWebFilter> tenantSecurityWebFilter(TenantProperties tenantProperties,
//                                                                                   WebProperties webProperties,
//                                                                                   GlobalExceptionHandler globalExceptionHandler,
//                                                                                   TenantFrameworkService tenantFrameworkService) {
//        FilterRegistrationBean<TenantSecurityWebFilter> registrationBean = new FilterRegistrationBean<>();
//        registrationBean.setFilter(new TenantSecurityWebFilter(tenantProperties, webProperties,
//                globalExceptionHandler, tenantFrameworkService));
//        registrationBean.setOrder(WebFilterOrderEnum.TENANT_SECURITY_FILTER);
//        return registrationBean;
//    }
//
//    // ========== Job ==========
//
//    @Bean
//    @ConditionalOnClass(name = "com.xxl.job.core.handler.annotation.XxlJob")
//    public TenantJobAspect tenantJobAspect(TenantFrameworkService tenantFrameworkService) {
//        return new TenantJobAspect(tenantFrameworkService);
//    }
//
//    // ========== MQ ==========
//
//    /**
//     * 多租户 Redis 消息队列的配置类
//     *
//     * 为什么要单独一个配置类呢？如果直接把 TenantRedisMessageInterceptor Bean 的初始化放外面，会报 RedisMessageInterceptor 类不存在的错误
//     */
//    @Configuration
//    @ConditionalOnClass(name = "com.handlink.framework.mq.redis.core.RedisMQTemplate")
//    public static class TenantRedisMQAutoConfiguration {
//
//        @Bean
//        public TenantRedisMessageInterceptor tenantRedisMessageInterceptor() {
//            return new TenantRedisMessageInterceptor();
//        }
//
//    }
//
//    @Bean
//    @ConditionalOnClass(name = "org.springframework.amqp.rabbit.core.RabbitTemplate")
//    public TenantRabbitMQInitializer tenantRabbitMQInitializer() {
//        return new TenantRabbitMQInitializer();
//    }
//
//    @Bean
//    @ConditionalOnClass(name = "org.apache.rocketmq.spring.core.RocketMQTemplate")
//    public TenantRocketMQInitializer tenantRocketMQInitializer() {
//        return new TenantRocketMQInitializer();
//    }
//
//    // ========== Redis ==========
//
//    @Bean
//    @Primary // 引入租户时，tenantRedisCacheManager 为主 Bean
//    public RedisCacheManager tenantRedisCacheManager(RedisTemplate<String, Object> redisTemplate,
//                                                     RedisCacheConfiguration redisCacheConfiguration,
//                                                     HandlinkCacheProperties handlinkCacheProperties,
//                                                     TenantProperties tenantProperties) {
//        // 创建 RedisCacheWriter 对象
//        RedisConnectionFactory connectionFactory = Objects.requireNonNull(redisTemplate.getConnectionFactory());
//        RedisCacheWriter cacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory,
//                BatchStrategies.scan(handlinkCacheProperties.getRedisScanBatchSize()));
//        // 创建 TenantRedisCacheManager 对象
//        return new TenantRedisCacheManager(cacheWriter, redisCacheConfiguration, tenantProperties.getIgnoreCaches());
//    }
//
//}
